Let's say, we have a server with Ubuntu 22.04 and ARM64 architecture. Also, we have the latest dotnet:
$ dotnet --version
7.0.102
I want to view JIT assembly output for a program, for example:
C.CurrentAction()
19fc: 64616572 strbtvs r6, [r1], #-1394 ; 0xfffffa8e
1a00: 6e6f635f mcrvs 3, 3, r6, cr15, cr15, {2}
1a04: 69735f64 ldmdbvs r3!, {r2, r5, r6, r8, r9, sl, fp, ip, lr}^
1a08: 6c616e67 stclvs 14, cr6, [r1], #-412 ; 0xfffffe64
1a0c: 68747000 ldmdavs r4!, {ip, sp, lr}^
1a10: 64616572 strbtvs r6, [r1], #-1394 ; 0xfffffa8e
1a14: 7474615f ldrbtvc r6, [r4], #-351 ; 0xfffffea1
We can do it on https://sharplab.io/, however this website doesn't support ARM64 at the moment. Also, we can do it in Visual studio, using Disassembly window, but we have a server without Visual studio.
I am looking for something similar to PrintAssembly in Java, which allows to get JIT output from command line.
I've found a few things, which could work for you, but it doesn't work for me on Linux (it works in Windows, though):
DOTNET_JitDisasm - https://devblogs.microsoft.com/dotnet/performance_improvements_in_net_7/
Using BenchmarkDotNet to get ASM - https://github.com/dotnet/BenchmarkDotNet/issues/1422
I have been trying and trying to make python.net work in my WPF application. I did a pip install of python.net and reference python.runtime.dll in my VS project. 4/5 of the included embedding tests failed though I couldn't figure out why (EDIT: When run individually they all seem to pass. I'm still suspicious). Here's the most recent code attempt in C#
PythonEngine.Initialize();
PythonEngine.AcquireLock();
PythonEngine.RunSimpleString("import sys\n"); PythonEngine.RunSimpleString("sys.path.append('C:/Users/mhames/AppData/Local/Continuum/Anaconda2/Lib/site-packages')\n");
PyObject np = PythonEngine.ImportModule("numpy");
Everything debugs fine until the last line, which throws a file not found exception. "Additional information: Could not load file or assembly 'numpy' or one of its dependencies. The system cannot find the file specified."
Previously, I've tried the format recommended on the python.net page:
using (Py.GIL())
{
dynamic np = Py.Import("numpy");
dynamic sin = np.sin;
Console.WriteLine(np.cos(np.pi * 2));
Console.WriteLine(sin(5));
double c = np.cos(5) + sin(5);
Console.WriteLine(c);
/* this block is temporarily disabled due to regression
dynamic a = np.array(new List<float> { 1, 2, 3 });
dynamic b = np.array(new List<float> { 6, 5, 4 }, Py.kw("dtype", np.int32));
Console.WriteLine(a.dtype);
Console.WriteLine(b.dtype);
Console.WriteLine(a * b);
*/
Console.ReadKey();
}
But this throws the exact same exception at the attempted numpy import. Before trying to run any python, the WPF application opens a system dialogue for a file selection, which I doubt is affecting anything but I'm desperate at this point. I also have both python 2.7 and python 3 on my computer, my PATH environment variable contains paths for both my versions of Anaconda, but I've also tried adding a specific PYTHONHOME and PYTHONPATH that point to only the python 2.7 folders.
Any ideas are much appreciated at this point.
I am trying to use aleagpu but I get the System.TypeInitializationException. I have tried to google what the problem is but I couldn't find any solution, so please help. The program is the simplest possible:
class Klazz
{
private const int N = 100;
private const int Length = 10000000;
var gpu = Gpu.Default;// here is the Exception thrown
public static void Unmanaged()
{
var data = new int[Length];
for (var k = 0; k < N; k++)
gpu.For(0, data.Length, i => data[i] += 1);
}
}
I am imagining that there is something wrong in my installation, because the program is a copied example from aleagpu's homepage.
My system is:
Windows 10
.NET v4.5.2
VS 2015 Community
NVIDIA GPU computing toolkit CUDA v8.0
Alea is installed from NuGet November 9. 2016
Alea (3.0.1)
Alea.IL (2.2.0.3307)
Alea.CUDA (2.2.0.3307)
Alea.CUDA.IL
(2.2.0.3307)
Alea.CUDA.Unbound (2.2.0.3307)
The variables in PATH is correct.
I have tried the AleaSample.CS.ParallelForAutoMemMgt as well with the same result.
It turns out that aleagpu is written in F#, and when you install FSharp.Core the program works.
Thanks to Ghosthack answering the question: Alea GPU Tutorial not compiling on VS 2015 Update 2 with FSharp.Core 4.4.0.0
Also, please make sure that you either install version 2.2 or version 3.x. For the new version 3.x you only need to install the Alea or the Alea.Fody package [https://www.nuget.org/packages/Alea/3.0.1][1] and do not mix with the 2.2 packages.
I am trying to create a "Hello World" example in R Language using R.Net version 1.5.5 (loaded from NuGet). Unfortunately, none of the online samples that I have seen work.
THIS IS WHAT I HAVE DONE:
Installed Microsoft R Open 3.2.4, the enhanced R distribution
Installed R Tools for Visual Studio (R version 3.2.4 (2016-03-16))
Created an R Project & tested a simple script
Created an MVC application & referenced R.Net version 1.5.5 from NuGet
MY PROBLEM:
All of the online examples I have seen must be using an earlier version because I cannot create an instance of the REngine for the LIFE of me! In fact, I keep getting:
Dll was not found
...yet C:\Program Files\Microsoft\MRO\R-3.2.4\bin\x64\r.dll does indeed exist.
Q: How do I create an instance of the REngine using R.Net version 1.5.5?
MY CODE LOOKS LIKE:
class Program
{
#region <Methods>
static void Main(string[] args)
{
SetupPath(); // current process, soon to be deprecated
using (REngine engine = REngine.CreateInstance("RDotNet"))
{
engine.Initialize(); // required since v1.5
CharacterVector charVec = engine.CreateCharacterVector(new[] {"Hello, R world!, .NET speaking" });
engine.SetSymbol("greetings", charVec);
engine.Evaluate("str(greetings)"); // print out in the console
string[] a = engine.Evaluate("'Hi there .NET, from the R engine'").AsCharacter().ToArray();
Console.WriteLine("R answered: '{0}'", a[0]);
}
Console.WriteLine("Press any key to exit the program");
Console.ReadKey();
}
public static void SetupPath()
{
var oldPath = System.Environment.GetEnvironmentVariable("PATH");
var rPath = #"C:\Program Files\Microsoft\MRO\R-3.2.4\bin\x64";
if (!Directory.Exists(rPath))
throw new DirectoryNotFoundException(string.Format(" R.dll not found in : {0}", rPath));
var newPath = string.Format("{0}{1}{2}", rPath, System.IO.Path.PathSeparator, oldPath);
System.Environment.SetEnvironmentVariable("PATH", newPath);
}
#endregion
}
I hate to answer my own question, but here it is...
The Microsoft R Open 3.2.4 enhanced R distribution installs x64 files. As such, running under ANY CPU will cause a failure because it will choose x86 (by default).
Under
Project Properties -> Build: in the "General" section
Choose x64 as your Platform Target
I've got an arbitrary list of .NET assemblies.
I need to programmatically check if each DLL was built for x86 (as opposed to x64 or Any CPU). Is this possible?
Look at System.Reflection.AssemblyName.GetAssemblyName(string assemblyFile).
You can examine assembly metadata from the returned AssemblyName instance:
Using PowerShell:
[36] C:\> [reflection.assemblyname]::GetAssemblyName("${pwd}\Microsoft.GLEE.dll") | fl
Name : Microsoft.GLEE
Version : 1.0.0.0
CultureInfo :
CodeBase : file:///C:/projects/powershell/BuildAnalyzer/...
EscapedCodeBase : file:///C:/projects/powershell/BuildAnalyzer/...
ProcessorArchitecture : MSIL
Flags : PublicKey
HashAlgorithm : SHA1
VersionCompatibility : SameMachine
KeyPair :
FullName : Microsoft.GLEE, Version=1.0.0.0, Culture=neut...
Here, ProcessorArchitecture identifies the target platform.
Amd64: A 64-bit processor based on the x64 architecture.
Arm: An ARM processor.
IA64: A 64-bit Intel Itanium processor only.
MSIL: Neutral with respect to processor and bits-per-word.
X86: A 32-bit Intel processor, either native or in the Windows on Windows environment on a 64-bit platform (WoW64).
None: An unknown or unspecified combination of processor and bits-per-word.
I'm using PowerShell in this example to call the method.
You can use the CorFlags CLI tool (for instance, C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\CorFlags.exe) to determine the status of an assembly, based on its output and opening an assembly as a binary asset you should be able to determine where you need to seek to determine if the 32BIT flag is set to 1 (x86) or 0 (Any CPU or x64, depending on PE):
Option | PE | 32BIT
----------|-------|---------
x86 | PE32 | 1
Any CPU | PE32 | 0
x64 | PE32+ | 0
The blog post x64 Development with .NET has some information about corflags.
Even better, you can use Module.GetPEKind to determine whether an assembly is PortableExecutableKinds value PE32Plus (64-bit), Required32Bit (32-bit and WoW), or ILOnly (any CPU) along with other attributes.
Just for clarification, CorFlags.exe is part of the .NET Framework SDK. I have the development tools on my machine, and the simplest way for me determine whether a DLL is 32-bit only is to:
Open the Visual Studio Command Prompt (In Windows: menu Start/Programs/Microsoft Visual Studio/Visual Studio Tools/Visual Studio 2008 Command Prompt)
CD to the directory containing the DLL in question
Run corflags like this:
corflags MyAssembly.dll
You will get output something like this:
Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 3.5.21022.8
Copyright (c) Microsoft Corporation. All rights reserved.
Version : v2.0.50727
CLR Header: 2.5
PE : PE32
CorFlags : 3
ILONLY : 1
32BIT : 1
Signed : 0
As per comments the flags above are to be read as following:
Any CPU: PE = PE32 and 32BIT = 0
x86: PE = PE32 and 32BIT = 1
64-bit: PE = PE32+ and 32BIT = 0
Just write your own. The core of the PE architecture hasn't been seriously changed since its implementation in Windows 95.
Here's a C# example:
public static ushort GetPEArchitecture(string pFilePath)
{
ushort architecture = 0;
try
{
using (System.IO.FileStream fStream = new System.IO.FileStream(pFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
using (System.IO.BinaryReader bReader = new System.IO.BinaryReader(fStream))
{
// Check the MZ signature
if (bReader.ReadUInt16() == 23117)
{
// Seek to e_lfanew.
fStream.Seek(0x3A, System.IO.SeekOrigin.Current);
// Seek to the start of the NT header.
fStream.Seek(bReader.ReadUInt32(), System.IO.SeekOrigin.Begin);
if (bReader.ReadUInt32() == 17744) // Check the PE\0\0 signature.
{
// Seek past the file header,
fStream.Seek(20, System.IO.SeekOrigin.Current);
// Read the magic number of the optional header.
architecture = bReader.ReadUInt16();
}
}
}
}
}
catch (Exception) { /* TODO: Any exception handling you want
to do, personally I just take 0
as a sign of failure */
}
// If architecture returns 0, there has been an error.
return architecture;
}
}
Now the current constants are:
0x10B - PE32 format.
0x20B - PE32+ format.
But with this method it allows for the possibilities of new constants. Just validate the return as you see fit.
DotPeek from JetBrains provides a quick and easy way to see msil (Any CPU), x86, and x64:
Try to use CorFlagsReader from this project at CodePlex. It has no references to other assemblies and it can be used as is.
[TestMethod]
public void EnsureKWLLibrariesAreAll64Bit()
{
var assemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies().Where(x => x.FullName.StartsWith("YourCommonProjectName")).ToArray();
foreach (var assembly in assemblies)
{
var myAssemblyName = AssemblyName.GetAssemblyName(assembly.FullName.Split(',')[0] + ".dll");
Assert.AreEqual(ProcessorArchitecture.MSIL, myAssemblyName.ProcessorArchitecture);
}
}
Below is a batch file that will run corflags.exe against all DLL files and EXE files in the current working directory and all sub-directories, parse the results and display the target architecture of each.
Depending on the version of corflags.exe that is used, the line items in the output will either include 32BIT, or 32BITREQ (and 32BITPREF). Whichever of these two is included in the output is the critical line item that must be checked to differentiate between Any CPU and x86. If you are using an older version of corflags.exe (pre Windows SDK v8.0A), then only the 32BIT line item will be present in the output, as others have indicated in past answers. Otherwise 32BITREQ and 32BITPREF replace it.
This assumes corflags.exe is in the %PATH%. The simplest way to ensure this is to use a Developer Command Prompt. Alternatively you could copy it from its default location.
If the batch file below is run against an unmanaged DLL or EXE file, it will incorrectly display it as x86, since the actual output from Corflags.exe will be an error message similar to:
corflags : error CF008 : The specified file does not have a valid managed header
#echo off
echo.
echo Target architecture for all exes and dlls:
echo.
REM For each exe and dll in this directory and all subdirectories...
for %%a in (.exe, .dll) do forfiles /s /m *%%a /c "cmd /c echo #relpath" > testfiles.txt
for /f %%b in (testfiles.txt) do (
REM Dump corflags results to a text file
corflags /nologo %%b > corflagsdeets.txt
REM Parse the corflags results to look for key markers
findstr /C:"PE32+">nul .\corflagsdeets.txt && (
REM `PE32+` indicates x64
echo %%~b = x64
) || (
REM pre-v8 Windows SDK listed only "32BIT" line item,
REM newer versions list "32BITREQ" and "32BITPREF" line items
findstr /C:"32BITREQ : 0">nul /C:"32BIT : 0" .\corflagsdeets.txt && (
REM `PE32` and NOT 32bit required indicates Any CPU
echo %%~b = Any CPU
) || (
REM `PE32` and 32bit required indicates x86
echo %%~b = x86
)
)
del corflagsdeets.txt
)
del testfiles.txt
echo.
I've cloned a super handy tool that adds a context menu entry for assemblies in Windows Explorer to show all available information:
Download from Releases · tebjan/AssemblyInformation.
One more way would be to use dumpbin from the Visual Studio tools on the DLL and look for the appropriate output:
dumpbin.exe /HEADERS <your DLL file path>
FILE HEADER VALUE
14C machine (x86)
4 number of sections
5885AC36 time date stamp Mon Jan 23 12:39:42 2017
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
2102 characteristics
Executable
32 bit word machine
DLL
Note: The above output is for a 32-bit DLL file
One more useful option with dumpbin.exe is /EXPORTS. It will show you the function exposed by the DLL file
dumpbin.exe /EXPORTS <PATH OF THE DLL FILE>
A more generic way - use the file structure to determine bitness and image type:
public static CompilationMode GetCompilationMode(this FileInfo info)
{
if (!info.Exists)
throw new ArgumentException($"{info.FullName} does not exist");
var intPtr = IntPtr.Zero;
try
{
uint unmanagedBufferSize = 4096;
intPtr = Marshal.AllocHGlobal((int)unmanagedBufferSize);
using (var stream = File.Open(info.FullName, FileMode.Open, FileAccess.Read))
{
var bytes = new byte[unmanagedBufferSize];
stream.Read(bytes, 0, bytes.Length);
Marshal.Copy(bytes, 0, intPtr, bytes.Length);
}
// Check DOS header magic number
if (Marshal.ReadInt16(intPtr) != 0x5a4d)
return CompilationMode.Invalid;
// This will get the address for the WinNT header
var ntHeaderAddressOffset = Marshal.ReadInt32(intPtr + 60);
// Check WinNT header signature
var signature = Marshal.ReadInt32(intPtr + ntHeaderAddressOffset);
if (signature != 0x4550)
return CompilationMode.Invalid;
// Determine file bitness by reading magic from IMAGE_OPTIONAL_HEADER
var magic = Marshal.ReadInt16(intPtr + ntHeaderAddressOffset + 24);
var result = CompilationMode.Invalid;
uint clrHeaderSize;
if (magic == 0x10b)
{
clrHeaderSize = (uint)Marshal.ReadInt32(intPtr + ntHeaderAddressOffset + 24 + 208 + 4);
result |= CompilationMode.Bit32;
}
else if (magic == 0x20b)
{
clrHeaderSize = (uint)Marshal.ReadInt32(intPtr + ntHeaderAddressOffset + 24 + 224 + 4);
result |= CompilationMode.Bit64;
}
else return CompilationMode.Invalid;
result |= clrHeaderSize != 0
? CompilationMode.CLR
: CompilationMode.Native;
return result;
}
finally
{
if (intPtr != IntPtr.Zero)
Marshal.FreeHGlobal(intPtr);
}
}
Compilation mode enumeration
[Flags]
public enum CompilationMode
{
Invalid = 0,
Native = 0x1,
CLR = Native << 1,
Bit32 = CLR << 1,
Bit64 = Bit32 << 1
}
Source code with explanation is at GitHub.
Another way to check the target platform of a .NET assembly is inspecting the assembly with .NET Reflector...
##~#€~! I've just realized that the new version is not free! So, correction, if you have a free version of .NET reflector, you can use it to check the target platform.
cfeduke notes the possibility of calling GetPEKind. It's potentially interesting to do this from PowerShell.
Here, for example, is code for a cmdlet that could be used: https://stackoverflow.com/a/16181743/64257
Alternatively, at https://stackoverflow.com/a/4719567/64257 it is noted that "there's also the Get-PEHeader cmdlet in the PowerShell Community Extensions that can be used to test for executable images."
A tool is sigcheck:
sigcheck c:\Windows\winhlp32.exe
Output:
Sigcheck v2.71 - File version and signature viewer
Copyright (C) 2004-2018 Mark Russinovich
Sysinternals - www.sysinternals.com
c:\windows\winhlp32.exe:
Verified: Signed
Signing date: 20:05 02.05.2022
Publisher: Microsoft Windows
Company: Microsoft Corporation
Description: Windows Winhlp32 Stub
Product: Microsoft® Windows® Operating System
Prod version: 10.0.19041.1
File version: 10.0.19041.1 (WinBuild.160101.0800)
MachineType: 32-bit
sigcheck -nobanner c:\Windows\HelpPane.exe
Output:
c:\windows\HelpPane.exe:
Verified: Signed
Signing date: 00:42 23.04.2022
Publisher: Microsoft Windows
Company: Microsoft Corporation
Description: Microsoft Help and Support
Product: Microsoft® Windows® Operating System
Prod version: 10.0.19041.1151
File version: 10.0.19041.1151 (WinBuild.160101.0800)
MachineType: 64-bit
An alternative to already mentioned tools is Telerik JustDecompile (free tool) which will display the information next to the assembly name:
I like the ILSpy tool. It shows not only architecture, but the target framework as well:
// linq2db, Version=3.0.0.0, Culture=neutral, PublicKeyToken=e41013125f9e410a
// Global type: <Module>
// Architecture: AnyCPU (64-bit preferred)
// Runtime: v4.0.30319
// This assembly is signed with a strong name key.
// This assembly was compiled using the /deterministic option.
// Hash algorithm: SHA1
So it is possible to determine if it is .NET Core 2.1, .NET Framework 4.6 or any other one: