8

I'm looking for a way to identify CP/M-80 (i.e. 8080 code) program files (.COM) from their content. A process usually known as Magic Number or File Signature detection, intended to identify a file by looking at their first few bytes for certain values and/or structure.

To narrow this down a bit, it will be fine if the distinction is good enough to separate CP/M-80 .COM files from their counterpart under MS-DOS(*1). That means, while a positive detection of a .COM file being 8080 code is great, already a negative detection of it not being 8086 code will do the trick.

I couldn't find any information. In addition, what I could figure out so far is rather limited:

  • CP/M 3 file may start with an optional header starting with a C9h (RET) marking a new, optional header used for RSX linking.

Basic CP/M programs often start with

  • Loading the stack pointer LXI SP,const (31 xx xx)
  • A variant thereof is LHLD adr/SPHL (2A xx xx F9)
  • Some even save SP first with LXI H,0/DAD SP/SHLD xxx/LXI SP,const
  • Often this is prefixed by a jump around some header JMP const/....suff.../LXI ... (C3 xx xx ...)

But I also found next to any other instruction when scanning files I have at hand - including pushing all registers onto the OS stack first...

The good part is that on a x86

  • C3h is a RET,
  • 31h is a XOR r/m16,r16,
  • 2Ah is a SUB r8,r/m8

The first is rather useless as a program start, but might be used to make prevent data files from execution, while the second may be unusual, but not unheard of to clear a register during setup. The last one is most definitive unusual for a program start, but as a 2...4 byte instruction any combination may show up as 4th byte, so a check for F9h is even weaker.

So either are rather weak indicators.


Question: Is there any (somewhat reliable) fast way for detecting CP/M-80 program files.


Background

From comments it seems that it would be of help to add why I'm looking for that information:

I'm in some NEC V20 nostalgia phase, here about the only useful improvement beside speed and 80186 instruction extension: The 8080 emulation mode. I'm tinkering with first drafts of a modified MS-DOS COMMAND.COM that would - or as of now should - detect when a .COM file is selected for execution if that one is possibly an 8080 one for CP/M-80. If this is the case it would

  • prepare the PSP according to CP/M (won't need much change),
  • add a BDOS to MS-DOS translation stub to top of memory (right below 64KiB),
  • Setup emulation vectors
  • invoke emulation mode and
  • clean up changed vectors after exit.

All of that not a big deal and already working fine, except for the detection part. And yes, I know, this has been done back then several times in form of loaders (which mine already is), but my attempt is to make it seamless, much like it was possible on CP/M-86.

Oh, and all of that should of course work on a 4.77 MHz XT without much delay - remember kids, grampa had to shovel his data with a toy sized scoop, both ways up hill and in the snow.


*1 - Using the same extension as CP/M-80 was a real stupid decision. CP/M-86 was at least so kind to go with .CMD - and drop memory images totally.

Raffzahn
  • 222,541
  • 22
  • 631
  • 918
  • 1
    You likely need to examine more of the file after making sure it isn't something else (like an .exe renamed .com). Scanning for DOS/BIOS and CPM/BDOS call sites is one option. The values around a CD opcode (INT on x86 and CALL on 8080) strongly suggest the OS. – Brian Oct 25 '22 at 12:48
  • @Brian maybe, but this needs to be a fast check, not a thruout analysis tool. – Raffzahn Oct 25 '22 at 12:58
  • 1
    I looked in libmagic1 but didn't see anything in it for CP/M executables. Although it does know how to identify CPM disk image data from the YAZE emulator. – Wayne Conrad Oct 25 '22 at 14:22
  • 3
    An interesting alternate way of looking at this is: Is it possible to create an executable that will run on both CP/M-80 and MS-DOS? Some specific combination of opcodes at the beginning that would effectively jump to one location in the file for CP/M-80 and a different location for MS-DOS and then execute appropriate (8080 or 8086) code? I have seen plenty of programming contests/puzzles/etc. over the years where the goal is to run one piece of code in multiple languages, the difference here is this is object code, not source code. – manassehkatz-Moving 2 Codidact Oct 25 '22 at 14:42
  • 2
    @manassehkatz-Moving2Codidact What a fun idea. Would it make a good puzzle on the codegolf site? – Wayne Conrad Oct 25 '22 at 15:49
  • 5
    @manassehkatz-Moving2Codidact The short answer is 'yes': https://en.wikipedia.org/wiki/Fat_binary#CP/M_and_DOS – john_e Oct 25 '22 at 16:04
  • 1
    @john_e Write that up as an answer - i.e., TL;DR No, and here's why – manassehkatz-Moving 2 Codidact Oct 25 '22 at 16:08
  • @john_e Oh, I like that. it's a complete different issue, but a nice approach. – Raffzahn Oct 25 '22 at 17:37
  • @manassehkatz-Moving2Codidact Not really, as the question is not to write a program running under both but detecting either. I did on purpose not write why I'm searching this, but maybe I should add that. – Raffzahn Oct 25 '22 at 17:38
  • The way I see it (but not my question) is that a Fat Binary that runs on both CP/M-80 and MS-DOS is the example that disproves the possibility of a Magic Number (or at least a simple Magic Number) - if you use such a file as an example of CP/M-80, I counter with "but it will run on MS-DOS just fine" and vice versa. – manassehkatz-Moving 2 Codidact Oct 25 '22 at 17:42
  • @manassehkatz-Moving2Codidact Doesn't disprove. Makes the MN just less reliable. Which is not a rare case with all these more or less compatible formats and extensions. – Raffzahn Oct 25 '22 at 18:17
  • Is the approach to produce a distribution of contained byte values too slow? Yes, it reads the whole file but just once with simple processing for each byte. The "pattern" of most and least used bytes could be an indicator. Operand values could just give a noisy background. -- Another approach is to detect at least programs produced by common compilers. This might catch the bigger part of all programs, and might give interesting insights. ;-) – the busybee Oct 26 '22 at 06:16
  • 1
    @manassehkatz-Moving2Codidact having fat binaries only means that the platform detection has to be more complex — the outputs should be at least “CP/M-80-only”, “MS-DOS-only”, and “CP/M-80 and MS-DOS”. (See also OS/2 Family binaries, and combined DOS/Windows programs.) – Stephen Kitt Oct 26 '22 at 07:35
  • 2
    @thebusybee: A lot of programs for both CP/M and DOS were assembled rather than compiled, so a search for the signatures of common compilers would draw a blank on a great many programs. – john_e Oct 26 '22 at 09:12
  • @john_e: Sure, I wrote several programs, all in assembly, but that was no paid work. As CP/M was written mostly in PL/M (IIRC) and DOS was derived from it, I'm curious to see numbers for system tools. 3rd party programs are another issue, companies tend to use higher level languages for less developer hours, presumably. Perhaps I should ask a separate question linking here, after Raffzahn built his tool. ;-) – the busybee Oct 26 '22 at 09:49
  • @thebusybee at least in DOS, many .COM programs (which is what this question is about) were written in assembly language, including commercial programs. See also Were later MS-DOS versions still implemented in x86 assembly? whose answers give more context on programming tools available at the time. – Stephen Kitt Oct 26 '22 at 09:58
  • 1
    @thebusybee I added a few clarifications what I'm searching plus some background information. hope that helps? – Raffzahn Oct 26 '22 at 10:17
  • @thebusybee Regarding the 'reading the whole file', this might in fact be possible as the program needs to be loaded anyway. I just don't see a way to do this without need for large memory structures and lots of processing time. Also data within the program (quite common back then, one wanted to have a single file, also loading and lookup wasn't as automatic (aka hidden by megabytes of library code) as today). – Raffzahn Oct 26 '22 at 10:39
  • I'd write an experiment, using 1/2 KB memory (256 buckets of uint16_t, because no count will be higher) and stare at the histograms. True, interspersed data are a problem, especially ASCII fills up certain ranges. I'd say, give it a try, and drop it if it does not work. But then you are certain that it does not work. :-D And concentrate on other ideas. – the busybee Oct 26 '22 at 10:44
  • 1
    This may be useless, but in a survey of > 2500 CP/M COM files lurking on my system: more than 80% of them have the first byte one of (c3|21|2a|31) - and more than half with the first, all of them are smaller than 52378 bytes (probably useless), but more than 85% of them are smaller than 16384 bytes. Knowing the 64K limit, do DOS COM files tend to be larger than CP/M-80 ones? – scruss Oct 26 '22 at 18:19
  • 1
    @scruss Wow. that is of great help. Would you mind to write the data as an answer? 2500 programs seem like a really good sample. Not sure if the size part is really making a difference, as COM is on both systems at first 64 KiB, only DOS may use more if the program does it's own segment management. So yes, that is another indicator I haven't though about - as soon as it's larger than 64KiB it's DOS (or some hack), as the CCP will deny loading. In fact, even the Best implementation I know offers 'only' 61KiB, so that may be a good start. Also, yes, DOS programs are in general larger. – Raffzahn Oct 26 '22 at 18:34
  • @Raffzahn in practice DOS .COM programs can’t be larger than 64K unless they’re MZ binaries, so after eliminating MZ binaries size wouldn’t be a discriminator. – Stephen Kitt Oct 26 '22 at 18:51
  • @StephenKitt Interesting information about DOS 5/6 checking the mit, as my knowledge was that DOS simply loads the first 64 KIB (minus a block or so). Back in DOS 2/3 times I did use that to attache data to COM files without making them EXE files. The whole idea is based around XT and DOS 2, set around 1984. Though, I will have to keep in mind that later DOS changed that behavious. – Raffzahn Oct 26 '22 at 19:01
  • I don't think it was even possible for CP/M COM files to have a magic number signature; they didn't have any kind of meta-data structure, they were just loaded into memory and execution started with the first byte. – Mark Ransom Oct 27 '22 at 17:43
  • @MarkRansom Sure, it was common to have a version/copyright notice at the start - Scruss' Answer showsthat 60% of >5000 binaries he checked start with C3, which is a jump. – Raffzahn Oct 27 '22 at 20:46
  • There is nothing except raw machine code starting at $100 in a CP/M-80 2.2. COM file. So what you basicially need is something that can tell whether a given file is valid Z80 machine code (including data at any point). Which can be self modifying, and jump inside instructions at will. The halting problem kicks in - I don't think there is any 100% safe rule for this. – Thorbjørn Ravn Andersen Oct 28 '22 at 11:54
  • @ThorbjørnRavnAndersen To start with, this is about 8080 code, not Z80 - Z80 will be as much a reason for exclusion as 8086. And I'm well aware about the environment - since ~1980 :)) Next, it's not about 100% proving that some code is all around valid 8080 code, but excluding with good degree such that not, while having not too much false rejects. At the end it's about looking for a real world solution. If that saves 50% possible crashes before start to execute, then it'll be great (using Scruss' data it looks more like 90+) It's not an exercise in Computer Science but Computer Praxis :)) – Raffzahn Oct 28 '22 at 13:18
  • You may want to do the same statistic analysis on the files you have. Also, as CP/M does not support subdirectories, how will you present the DOS environment to the CP/M programs? – Thorbjørn Ravn Andersen Oct 28 '22 at 16:44
  • @ThorbjørnRavnAndersen I'm not really doing anything new, it has been done already in the 1980s. For the directories. These are CP/M programs, they do not expect directories, nor do they need them. Thus data has to be in the same directory as the program - which would be presented as the drive it was started off - exactly like DOS does. For teh context of the CP/M program it's much like a sandbox, as there are no ways to change out of that directory. As a first step this should be fine for most applications. especially since there is no real size limit for FAT directories. Beyond that ... 1/+ – Raffzahn Oct 28 '22 at 16:58
  • @ThorbjørnRavnAndersen ... one could think of using the (up to) 16 drives CP/M supports by assigning directories to each (B..P - A as 'boot' drive ). Maybe sans two for real floppies. if that is really not sufficient (nor sure what CP/M program would need more) it would be of course possible to use the user numbers. Essentially the same way CP/M used to manage for hard disks. That gives up to 256 possible 'directories' in direct access. Sounds rather sufficient for programs which are usually not handling more than one or two at a time. 2/- – Raffzahn Oct 28 '22 at 17:03
  • @Raffzahn I am well aware that the "emulate CP/M on DOS" problem has been tackled long ago. What I was getting at was to use the location/drive as an indicator of the platform, meaning that everything on drive B: is CP/M and everything on C: is DOS for instance. But if the statistical numbers are good enough for you, something like that is not needed, and it is much more fun to code a guesser. – Thorbjørn Ravn Andersen Oct 28 '22 at 23:10
  • @ThorbjørnRavnAndersen Err ... now you got me. How can a drive help to decide what type of binary a random .COM file is? – Raffzahn Oct 28 '22 at 23:14
  • If you know when adding the file to the system what origin is has. In other words, you add metadata yourself. My guess is that the fun is for this to be truly random, but I just wanted to explain what I was thinking of. It is not important. – Thorbjørn Ravn Andersen Oct 28 '22 at 23:19
  • @ThorbjørnRavnAndersen Why? I'm serious interested to learn your idea Especially what the use case is you had in mind. As it seems to be a complete different one. The setup in question is a DOS system with a COMMAND.COM capable of starting DOS programs as well as 8080 CP/M files. A random drive and directory is active, a command is entered and COMMAND is about to search along the PATH for a .EXE or .COM file. If a .COM file is found, it needs to decide if the emulation needs to be set up or better not. (A dedicated loader would need to do the same to avoid a crash). – Raffzahn Oct 28 '22 at 23:27
  • Something as simple as files on the C-drive are DOS and files on another drive (A,B emulated probably) would be CP/M and then make the decision based on that. That is probably not what you want. – Thorbjørn Ravn Andersen Oct 29 '22 at 13:08

2 Answers2

12

At user Raffzahn's request, I've expanded a comment into an overly complex statistical answer. In summary, if a random *.COM file is 27392 bytes or fewer and starts with one of twelve byte values, it is very probably a CP/M-80 executable.

There is no practical way to use “magic numbers” to identify CP/M-80 executable files. The Linux file command typically identifies them as one of the following MIME types:

  • application/octet-stream
  • application/x-dbt
  • application/x-dosexec
  • application/x-matlab-data
  • application/x-tex-tfm
  • application/zlib
  • image/x-tga
  • text/plain

In a review of 5510 unique *.COM files lying about my hard drive (mostly from the Oakland CP/M Archive CD-ROM, the Walnut Creek CP/M CD-ROM and z80pack), with potential MS-DOS or other non-8080-compatible executables weeded out, I found:

Size

  • 25% are 1792 bytes or fewer
  • 50% are 4864 bytes or fewer
  • 75% are 12288 bytes or fewer
  • 95% are 27392 bytes or fewer
  • All of them are 53504 bytes or fewer.

First byte

  • 60% have a first byte (c3)
  • 75% have a first byte (c3|21|2a)
  • 80% have a first byte (c3|21|2a|31)
  • 90% have a first byte (c3|21|2a|31|18|ed|00|cd)
  • 95% have a first byte (c3|21|2a|31|18|ed|00|cd|0e|01|11|3a)

MS-DOS

Using all 3508 unique *.COM files on the Power DOS CD ROM (Walnut Creek) (July 1995) and the Simtel MSDOS 1996-09 CDs, I found:

Size

  • 25% are 768 bytes or fewer
  • 50% are 3072 bytes or fewer
  • 75% are 9984 bytes or fewer
  • 80% are 12800 bytes or fewer
  • 85% are 15872 bytes or fewer
  • 90% are 21760 bytes or fewer
  • 95% are 32768 bytes or fewer
  • All of them are 187904 bytes or fewer. These must have some additional payload to be this large.

(So the typical file size could be smaller under MS-DOS. Perhaps some of these have been packed, a technology that wasn't as effective or widespread under CP/M.)

First byte

  • 45% have a first byte (e9)
  • 65% have a first byte (e9|eb|8c)
  • 75% have a first byte (e9|eb|8c|b4|4d)
  • 80% have a first byte (e9|eb|8c|b4|4d|b8)
  • 90% have a first byte (e9|eb|8c|b4|4d|b8|e8|fc|24|bc|bb)
  • 95% have a first byte (e9|eb|8c|b4|4d|b8|e8|fc|24|bc|bb|be|ba|fb|9c|b0|1e|33)

Note that none of these common MS-DOS first bytes are shared with CP/M-80 *.COM files. Checking the first byte may be all you need to do. Like all statistical assumptions, however, you won't catch every last outlier.

scruss
  • 21,585
  • 1
  • 45
  • 113
  • 2
    sample corpus and methodology can be made available, if anyone cares enough about this – scruss Oct 27 '22 at 13:28
  • 2
    Statistical fingerprinting. Nice. You could also train an AI on a labelled set of DOS .com files and CP/M .com files. – hippietrail Oct 27 '22 at 14:21
  • 1
    @scruss How lovely. You're awesome. To to make sure I read this right, the slashes are meant as or, meaning 60% start by C3h JMP a16, 15% with 21h LXI H,i16 or 2Ah LHLD a16, 5% with 31h LXI SP,i16 and so on? 18h and EDh are as well nice finds as these are most likely Z80 programs. 01h&11h might be variants loading SP via BC or DE - assuming the next is some way to move that into SP. As the saying goes, no good deed goes unpunished, have you tried to look at the next instruction as well? Again, that statistic is a real great help. Thanks you. – Raffzahn Oct 27 '22 at 14:47
  • 1
    @Raffzahn - oops, I guess I'm too used to using egrep. Also, I'm using a percentage exceedance (can't help it; former due diligence engineer). The 75% line means: of all the probably CP/M COM files I could find, ¾ or more of them start with the byte c3 or with the byte 21 or with the byte 2a. Consequently, less than ¼ of the COM files start with any of the other 253 byte values. I wouldn't infer anything from the intervals between the %age steps: it won't be exactly 15% that have first byte 21 or 2a. I can add raw percentages later – scruss Oct 27 '22 at 15:49
  • @hippietrail - AI yes, but it would melt Raffzahn's poor NEC V20 trying to load the model into COMMAND.COM – scruss Oct 27 '22 at 15:54
  • 1
    @scruss "it would melt Raffzahn's poor NEC V20" - so far it runs remarkably cool at 4.77 MHz .. 9.54 MHz (1) ... Cool as a Sloth :)) 1 -I 'pimped' that machine back then not only with a V20 but as well a variable speed clock generator which configures maximum clock speed between 4.77 and 9.54, depending on which memory address is accessed. A Sloth riding a Ferrari :) – Raffzahn Oct 27 '22 at 16:11
  • @Raffzahn - I tried running binaries through a batch disassembler, but it produced too varied information to be useful. Multiple bytes likewise. Interestingly, only 42 out of the total 256 values for first bytes are used at all. Values 5b-75 (amongst many others) aren't seen at all – scruss Oct 27 '22 at 23:39
  • Interesting DOS part - how much are over 64 Ki?. E9h/EBh makes again much sense as they are jumps, most likely around some version/copyright notice - a habit like with CP/M. For the 8Ch, I would put a high bet on the next byte being C8h, as in `MOV AX,CS' the signature of programs not trusting DOS about any segment register except CS :)) Multi byte tests would need to be according to the first byte, so rather specific signatures - like the address after JMP (C3h in 8080, E9h/EBh for 8086) will of course depend on the text to be jumped across. – Raffzahn Oct 28 '22 at 01:33
  • 1
    I would think the last analysis (DOS) contains the solution. All 90% instructions will not make any sense in terms of a CP/M-80 program(or if at all it'll be based on quite obscure effects). Of the 95% list only FBh EI, 1Eh MVI E,d8 and 33h INX SP might maybe make sense. So this gives already a 95% detection rate for non-CP/M. So together with the 80% 8080 list I do think we get a pretty good detection of either, leaving only a small grey area. – Raffzahn Oct 28 '22 at 02:27
  • This would be a really fun coding challenge. I don't know if there's some forum to pose challenges like this. First thing needed is a good training set. I wish more of the retrocomputing YouTube channels did coding as well as restoration, repairs, and playing old games incredibly badly. Maybe Dave's Garage? He's an old MS programmer and has CP/M machines and has done code challenge type things before. – hippietrail Oct 28 '22 at 04:39
  • Firefox/Mozilla contains code to stochastically work out the text encoding and language in a webpage since what's declared in the HTML or HTTP headers is often wrong. That code could be repurposed to identify headerless binary executables I bet. – hippietrail Oct 28 '22 at 04:41
  • Just for completeness: a 0-byte .COM file is a CP/M-80 command - and often quite a useful one. – Martin Kochanski Oct 28 '22 at 07:57
  • 1
    From that corpus, all the MS-DOS .COM files larger than 64K are MZ binaries and can be detected as such. – Stephen Kitt Oct 28 '22 at 13:14
  • 1
    @hippietrail yes, would be a nice thing, except for two factors: a) Either file (80 or 86) might hold a large amount of ASCII making differentiation quite hard hard and b) Firefox got the resources of a modern PC with multi mega-herz and multi-megabyte (if not giga for both) at hand to load and crunch all data. I need to do this by peeking at max on the first 128 (or maybe 512) bytes and doing so on a 4.77 MHz 8088. – Raffzahn Oct 28 '22 at 13:23
  • @StephenKitt are they? Have you checked it, or just assuming? I mean 4D as first character does already show up in Scruss' list. Might be interesting to get a statistic how many .COM do start with MZ - and how many of non-MZ being larger than 32 or 64Ki. (Also MZ is excluded in the solution by default, as detecting MZ will automatic handle it as EXE - as it is done by standard handling. – Raffzahn Oct 28 '22 at 13:29
  • @Raffzahn I checked, I was intrigued by the “These must have some additional payload to be this large.” comment and wanted to see if that was the case. The fact that 4D features in the stats suggests that MZ binaries weren’t filtered out. – Stephen Kitt Oct 28 '22 at 13:53
  • @StephenKitt Oh, that's cool. Thanks for checking. Do you also have a percentage of MZ among all those .COM? I'm already filtering them out, so it's only for curiosity. Likewise what's the larges .COM that is not a MZ within that collection? – Raffzahn Oct 28 '22 at 14:00
  • 1
    @Raffzahn just looking at the Simtel CDs, I find 3869 files with a .COM extension, most of which are DOS binaries, and at least 194 of those are MZ binaries (I’m just running file over them, so it gets confused by a few files with embedded data that matches other signatures; but the reported MZ binaries are all accurately identified). The largest non-MZ binary is A51.COM in PS51A123.ZIP, a 8751 cross-assembler, which is 64,997 bytes long. There are four larger .COM files, including 4DOS.COM. – Stephen Kitt Oct 28 '22 at 14:23
  • 1
    There's another edge case: a file beginning MZ will be treated as a .COM file if it's too small to contain a valid .EXE header. See, for example, MSDOS 2.11 exec.asm lines 326-7. – john_e Oct 28 '22 at 14:29
5

A process usually known as Magic Number or File Signature detection, intended to identify a file by looking at their first few bytes for certain values and/or structure.

As you have found out, there is nothing like a Magic Number like you'd find in an ELF binary or anything like that. Rather, the fact it's executable is determined by CP/M by looking at the filename's extension. Yes, it's another bad idea, but that's how it worked.

Question: Is there any (somewhat reliable) fast way for detecting CP/M-80 program files.

You could look at Markov Chains; essentially read the instruction stream and see which of your models best model your observed state transitions. So then you'd see if your program is an 80186 MS-DOS program, or an CP/M-80 program, or this, or that, or the other. The technique would normally require heavy use of floating point, so maybe not exactly fast if you're intending to do this detection on the V20 itself.

I have no idea if this is a workable idea.

I'm tinkering with first drafts of a modified MS-DOS COMMAND.COM that would - or as of now should - detect when a .COM file is selected for execution if that one is possibly an 8080 one for CP/M-80.

Cool idea! The best of luck with it. Depending on where you want to take this idea, you could consider using some kind of meta-data. See if there's an unused bit in the filesystem, or use a different filename extension, or keep a reference to the executable in another file, or something along those lines.

Or, require the user to explicitly invoke your compatibility layer, just like a Linux user has to type wine minesweeper.exe. Just typing minesweeper.exe on Linux will result in a permissions error.

Using the same extension as CP/M-80 was a real stupid decision. CP/M-86 was at least so kind to go with .CMD - and drop memory images totally.

This part reminded me of a question I asked some years ago which, while being about UNIX and so not directly relating to anything like a solution for you, has some insights of various kinds in the answers. In particular, finding that a binary was for the wrong architecture, I surmise was not a problem that anyone was facing.

Omar and Lorraine
  • 38,883
  • 14
  • 134
  • 274
  • 5
    Typing minesweeper.exe on Linux won't necessarily result in a permissions error. If you've put minesweeper.exe in your PATH (otherwise, you need ./minesweeper.exe) and run chmod +x minesweeper.exe and then registered the MZ magic number with the kernel's binfmt_misc system, then it'll just transparently hand it off to Wine. – ssokolow Oct 26 '22 at 11:25
  • 2
    @ssokolow Actually that is how it works in WSL2. If you execute a Windows binary it is run normally. – Thorbjørn Ravn Andersen Oct 28 '22 at 12:00