Discussion:
Fat Binary - MS-Windows and four Linux
(too old to reply)
Frederick Gotham
2020-10-24 13:20:40 UTC
Permalink
This is a follow-up to "Making a Fat Binary for Linux and Mac" which I
multi-posted two days ago to three newsgroups:

comp.lang.c, comp.lang.c++, comp.unix.programmer

I got the most responses on 'comp.lang.c', which you can see here:

https://groups.google.com/forum/#!topic/comp.lang.c/Qev_btMilNI

I have now made a fat binary that contains 5 executable programs:

* Linux arm32
* Linux arm64
* Linux x86_32
* Linux x86_64
* MS-Windows x86_32

For the Microsoft Windows executable file, I went with a 32-Bit
executable because it will run on both 32-Bit and 64-Bit versions of
MS-Windows.

So here's how my 'combined Linux and MS-Windows' script looks now. Note
that each line begins with four spaces. This script will run as an 'sh' shell script on Linux, and will run as a batch file on MS-Windows.

[BEGIN SCRIPT]
:; if [ -z 0 ]; then #
@echo off
goto :MICROSOFT
fi

# Linux shell script starts here

# x86 32-Bit = i386, i686
# x86 64-bit = x86_64
# arm 32-Bit = arm
# arm 64-Bit = aarch64 aarch64_be armv8b armv8l

arch=`uname -m`

case ${arch} in
i386|i686)
skip=000000018788
count=000000005464
;;
x86_64)
skip=000000024252
count=000000010216
;;
arm|armv7l)
skip=000000034468
count=000000005528
;;
aarch64|aarch64_be|armv8b|armv8l)
skip=000000039996
count=000000010080
;;
*)
exit 1
;;
esac

tmpfile=$(mktemp /tmp/fatbinary_${arch}.XXXXXXXXXX)
dd if="$0" of=${tmpfile} bs=1 skip=${skip} count=${count} > /dev/null 2>&1
chmod +x ${tmpfile}
${tmpfile} "$@"
retval=$?
rm -rf "$tmpfile"
exit ${retval}

# Microsoft batch file starts here
:MICROSOFT
REM The next 6 lines are just for making a temporary file
:loop
set /a y$$=%random%+100000
set y$$=temp%y$$:~1,2%.%y$$:~-3%
if exist "%temp%\%y$$%.exe" goto loop
set "y$$=%temp%\%y$$%"
set "tempfile=%y$$%.exe"
findstr /v /c:" " "%~f0" > %tempfile%
%tempfile% %*
set "finalerrorcode=%ERRORLEVEL%"
del /f /q %tempfile%
exit /b %finalerrorcode%
[END SCRIPT]

The Linux part of the above script has "\n" line endings, whereas the
Microsoft part of the above script has "\r\n" line endings. See the
first link at the end of this post to get the original file.

As for the program for which I chose to make a fat binary, I went with a
sha256 digest calculator, using code by Alain Mosnier from repository:
https://github.com/amosnier/sha-2

I have turned Mosnier's code into a single-source-file C program that
calculates the sha256 digest of its first command line argument. For the
C code, see the second link at the end of this post.

I compiled this C program 5 times and got the 5 following binaries:

-rwxr-xr-x 1 root root 17422 Oct 24 11:10 prog_mswin_x86_32.exe
-rwxr-xr-x 1 root root 5464 Oct 24 13:50 prog_x86_32
-rwxr-xr-x 1 root root 10216 Oct 24 13:50 prog_x86_64
-rwxr-xr-x 1 root root 5528 Oct 24 13:50 prog_arm32
-rwxr-xr-x 1 root root 10080 Oct 24 13:50 prog_arm64

(See download links 3-7 at the end of this post)

I concatenated my script with these 5 binaries as follows:

cat script.txt prog_mswin_x86_32.exe prog_x86_32 prog_x86_64 prog_arm32 prog_arm64 > fatsha256.bat

The result is my fat binary with size 50 kilobytes:

-rwxr-xr-x 1 root root 50076 Oct 24 13:51 fatsha256.bat
(See download link 8 at the end of this post)

This file can be executed at the command line on both Linux and MS-Windows:

fatsha256.bat "This is my message"

And it prints the digest:

3311b7c0bd91b6c73a38212de8ade31c51910f17480ad212ed2b9798a35b7747

I have verified it works on:
* Linux arm32
* Linux arm64
* Linux x86_64
* MS-Windows x86_32

It should also work on Linux x86 32-Bit, let me know if someone tries
it.

Links:

1: http://virjacode.com/experimental2/script.txt
2: http://virjacode.com/experimental2/sha256.c
3: http://virjacode.com/experimental2/prog_arm32
4: http://virjacode.com/experimental2/prog_arm64
5: http://virjacode.com/experimental2/prog_x86_32
6: http://virjacode.com/experimental2/prog_x86_64
7: http://virjacode.com/experimental2/prog_mswin_x86_32.exe
8: http://virjacode.com/experimental2/fatsha256.bat
Frederick Gotham
2020-10-24 22:07:16 UTC
Permalink
The MS-Windows executable file is a PE file that contains a 'DOS stub' at the beginning of it. This stub is a 16-Bit DOS program that typically prints "This program cannot be run in DOS mode".

If I replace the stub with a 16-Bit version of the sha256 program, then the fat binary will also run on MS-DOS 6.22.
Loading...