Darling: Can't run Go programs

Created on 20 Nov 2016  ·  18Comments  ·  Source: darlinghq/darling

Try run helloworld

package main
func main(){}

$ ./test
dyld: Cannot execute binary file: This executable is not position independent and your vm.mmap_min_addr is too low to load it. As low as 4096 is needed.

Bug

Most helpful comment

@bugaevc They do the same crap on Linux, too, so I guess it must be their philosophy or something. But you can try that...

All 18 comments

You need to lower your vm.mmap_min_addr as suggested. There is an error in the error message - it should say "is not low enough to load it".

I set vm.mmap_min_addr="4096", but

Beware! This executable does not link against libSystem. It is very likely a copy-protected executable which makes direct system calls.
Darling currently cannot support that.
Segmentation fault: 11

It's sad 😢

Could you please post the binary somewhere?

The next step is to update the error message to also mention Go. Because, unfortunately, the binary you posted really contains direct system calls and doesn't use standard system libraries :-( I don't understand why on Earth were Go binaries designed this way. Hell, they even depend on such internal undocumented features as comm page. Apple could break compatibility at any point in future!

There aren't many ways of fixing this situation. If we were talking about arm, then it would be possible to easily scan the binary for syscall instructions and patch it in memory, because arm and thumb instructions have a fixed size (4/2 bytes), unlike x86. On x86, however, all we could do is to inject a special thread into the process and run ptrace(PTRACE_SYSEMU) whilst dispatching the system calls to Darling (and optionally patching the binary in memory to make the next call faster).

FYI - the Go project violates Apple's recommendations.
https://developer.apple.com/library/content/qa/qa1118/_index.html

Apple does not support statically linked binaries on Mac OS X. A statically linked binary assumes binary compatibility at the kernel system call interface, and we do not make any guarantees on that front.

Shipping a statically linked binary entails a significant compatibility risk. We strongly recommend that you not do this. If you choose to ignore our advice, please make sure that your customers are informed of this risk.

I haven't seen Go people do this. Should we reach out to them?

@bugaevc They do the same crap on Linux, too, so I guess it must be their philosophy or something. But you can try that...

I believe Linux does provide stability guarantees about syscall API and ABI.

@LubosD this could be easily fixed by implementing syscalls in kernel-space with a custom system call table instead of hacking the standard libraries to run translated syscalls.

@M1cha I've done that in the past as part of a contract (a Darling-like solution for iOS apps), but it's unacceptable. You cannot expect users to patch their kernels...

@LubosD You need a kernel module anyway which needs to be compiled for every system separately, also Linux is opensource and you really shouldn't care about people using old kernels.

To make this more generic you could send a patch to the mailing list which allows implementing system call tables from within a kernel module.

There is a big difference between using an old kernel (and simply upgrading) and having to patch your kernel.

It would be lovely to have a generic way, but I don't see this being accepted into the kernel. The kernel guys only merge patches that benefit multiple users. See the last section of this blogpost. Darling would benefit from the patch that was sent into the mailing list, it's even about implementing an already existing interface (that is just not implemented on x86) and did it get merged? NO. I even mailed into LKML about it and got zero response.

Moreover, Darling would require an additional gate at 0x82 (for sysdep calls). Mapping this into a kernel module is not possible for a good reason (it could easily crash the kernel).

To sum it up

  • There is a very slim chance of such patchset being accepted upstream.
  • This would only be needed to support broken programs that go against Apple's recommendations and will stop working over time, because Apple frequently kills old system calls and replaces them with new ones. They simply don't guarantee ABI stability on kernel interfaces.

As I've probably said, I've already done something like this on Linux/ARM for a Chinese company. It was fantastic, but I just don't see it happening for vanilla Linux.

Even though I think that the problem with your patch getting merged has very different reason(e.g. the issue that u address has been talked about and denied a lot in past and that your patch is just one out of a million and you're not exactly a popular developer so it's easy for a patch to get lost), I agree with you that there are too many disadvantages for just one advantage.

So you have two options(both should only be used for static application compat and not by default):

  • (the bad one) symbol hooking from withing a kernel module. yes, this is possible but very hacky, you could write a branch instruction to the syscall enter address
  • (the more complicated but preferred one) using ptrace to catch and translate system calls.

Either way, right now I'd focus on getting darling stable and compatible with big GUI applications like office or photoshop instead of solving such annoyances. We can come back to this later when you've reached that goal.

@M1cha Agree.

golang/go#17490

On macOS and iOS, the runtime now uses libSystem.so instead of calling the kernel directly. This should make Go binaries more compatible with future versions of macOS and iOS. The syscall package still makes direct system calls; fixing this is planned for a future release.

https://golang.org/doc/go1.11#runtime

libSystem.so, 🤦‍♂️, but yay, Go 1.11 binaries should work then, can someone test?

This now works, in general. But there's issue #581 when building Go apps.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pmannle picture pmannle  ·  7Comments

LubosD picture LubosD  ·  3Comments

ahyattdev picture ahyattdev  ·  5Comments

andyneff picture andyneff  ·  3Comments

wusikijeronii picture wusikijeronii  ·  4Comments