I'm facing a dead end trying to create MacOS mach-o executable that works.
created simple console application in visual studio; simple.exe
I've tried 2 routes with mkbundle:
using mkbundle the
1. the old (--custom) way:
after setting extra CC compiles args , and PATH for pkg-config:
$ mkbundle --deps -v -L "$PWD" -L "/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5" -o $BASE/Simple.app/Contents/MacOS/simple_exe ./simple.exe
The produced simple_exe fails to start:
$ cd $BASE/Simple.app/Contents/MacOS/
$ ./simple_exe
Segmentation fault: 11
though, it's perfect mach-o for the OS, so signing this file succeeds.
2. using (--simple) mkbundle by either --cross or --sdk options:
$ mkbundle -v --simple --cross mono-6.8.0-osx-10.9-x64 -o $BASE/Simple.app/Contents/MacOS/simple_exe ./simple.exe
The compiled (well, rather say constructed) executable runs successfully:
$ cd $BASE/Simple.app/Contents/MacOS/
$ ./simple_exe
Hello World!
the resulting executable is signed by Xamarin
tried 2 options for deployment process:
A- Leaving the executable it as is; signed by Xamarin's Application Certificate
- Code sign other assets beside this executable with my Application Certificate.
- Signing The whole App bundle succeeds
$codesign --strict --sign "$CERT" $BASE/Simple.app
- Making installer .pkg and signing it with Installer Certificate succeeds.
Now, Notarization from apple result : "Invalid"
issue: code null
path "Simple.pkg/pkgbuild_Simple.pkg Contents/Payload/Applications/Simple.app/Contents/MacOS/simple_exe"
message "The signature of the binary is invalid."
architecture "x86_64"code null
B- Force resigning the bundled executable with my Application Certificate.
It gives (__LINKEDIT segment does not cover the end of the file (can't be processed) in: /Users/assem/bundles/SimpleApp/payload/Applications/Simple.app/Contents/MacOS/simple_exe
)
I've been able to "patch" it and increasing file size inside __LINKEDIT Segment (along with aligned up VM size), and String table size under SYMTAB Load Commands to cover up injected assembles over the mkbundled Mono executable.
After Patching, I can re-sign the resulting executable with my Certificate. but, if when I run it, it outputs the mono command line options help message (As if the resulting binary was mono itself and the link/reference to the assemblies bundled inside is broken).
$./SimpleApp/payload/Applications/Simple.app/Contents/MacOS/Simple_exe
Usage is: mono [options] program [program-options]
Development:
--aot[=<options>] Compiles the assembly to native code
--debug[=<options>] Enable debugging support, use --help-debug for details
--debugger-agent=options Enable the debugger agent
--profile[=profiler] Runs in profiling mode with the specified profiler module
--trace[=EXPR] Enable tracing, use --help-trace for details
--jitmap Output a jit method map to /tmp/perf-PID.map
--help-devel Shows more options available to developers
.
.
.
.
etc..
note: The original Xamarin's signature was in the middle of the mkbundled O-Mach executable, then followed by simple.exe as well as dependent assemblies. After patching and re-signing with my certificate. the code signature is attached to the end of the bundled file , beyond embedded assemblies.
To make a long story short: mkbundle either compiles a (sign-able) native mach-o binary , but when it runs immediately crashes with segmentation fault. or, constructs a binary file the runs but fails to be deployed inside signable mac bundle and notarized installer pkg.
Stack:
- MacOS Catalina (Also tried all of the above on Mojave)
- Mono 6.8.0 (Also tried on 6.6.0 , 6.4.0, and 6.0.0)
- XCode Version 11.3.1 (also tried on older 10.x)