Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime: unknown pc on macOS Mojave with cgo app built on macOS Catalina #37849

Closed
ghost opened this issue Mar 13, 2020 · 4 comments
Closed

runtime: unknown pc on macOS Mojave with cgo app built on macOS Catalina #37849

ghost opened this issue Mar 13, 2020 · 4 comments

Comments

@ghost
Copy link

ghost commented Mar 13, 2020

What version of Go are you using (go version)?

$ go version
go1.14 darwin/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env(BUILD ENV) Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/tsekar/Library/Caches/go-build"
GOENV="/Users/tsekar/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/tsekar/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/Cellar/go/1.14/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.14/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/10/5k1r_qh9087cmp3z7mz3zk3c0000gy/T/go-build080838874=/tmp/go-build -gno-record-gcc-switches -fno-common"
go env(DEPLOY ENV) Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/user/Library/Caches/go-build"
GOENV="/Users/user/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/user/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/yn/km_26yfs355779hk5fvj6rzh0000gn/T/go-build703892931=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

Built a CGO app that calls objective-c functions from within Go Code. The app was built on macOS catalina. It runs fine on macOS catalina, and crashes with unknown pc on mojave. The code is as follows

main.go

package main

import (
	"fmt"
	"unsafe"
)

/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework Foundation -framework CoreServices
#include "mac_fruits.h"
*/
import "C"

func cstring(s *C.NSString) *C.char { return C.nsstring2cstring(s) }

func gostring(s *C.NSString) string { return C.GoString(cstring(s)) }

func nsarraylen(arr *C.NSArray) uint { return uint(C.nsarraylen(arr)) }

func nsarrayitem(arr *C.NSArray, i uint) unsafe.Pointer {
	return C.nsarrayitem(arr, C.ulong(i))
}

func cleanFruits(arr *C.NSArray) []string {
	var result []string
	length := nsarraylen(arr)

	for i := uint(0); i < length; i++ {
		nsPath := (*C.NSString)(nsarrayitem(arr, i))
		u := gostring(nsPath)
		result = append(result, u)
	}

	return result
}

func main() {
	fruits := cleanFruits(C.getFruits())
	fmt.Printf("Fruits are %v", fruits)
}

mac_fruits.h

#import <Foundation/Foundation.h>

const NSArray* getFruits();
const char* nsstring2cstring(NSString *s);
int nsnumber2int(NSNumber *i);
unsigned long nsarraylen(NSArray *arr);
const void* nsarrayitem(NSArray *arr, unsigned long i);

mac_fruits.m

#import "mac_fruits.h"

const NSArray* getFruits() {
    @autoreleasepool {
        NSArray *fruits = [NSArray arrayWithObjects: @"apple", @"orange", @"lemon", @"melon", nil];
        NSMutableArray *result = [[NSMutableArray alloc] init];
        for (NSString *fruitId in fruits) {
            NSString *string =  CFBridgingRetain(fruitId);
            [result addObject: string];
        }
        return result;
    }
}

const char* nsstring2cstring(NSString *s) {
    if (s == NULL) { return NULL; }
    const char *cstr = [s UTF8String];
    return cstr;
}

unsigned long nsarraylen(NSArray *arr) {
    if (arr == NULL) { return 0; }
    return arr.count;
}

const void* nsarrayitem(NSArray *arr, unsigned long i) {
    if (arr == NULL) { return NULL; }
    return CFBridgingRetain([arr objectAtIndex:i]);
}

What did you expect to see?

Code running smoothly, with the output
Fruits are [apple orange lemon melon]

What did you see instead?

On macOS Catalina:
Fruits are [apple orange lemon melon]

On macOS Mojave:

dyld: lazy symbol binding failed: Symbol not found: _objc_alloc_init
  Referenced from: /Users/btfuser/./dummy_test (which was built for Mac OS X 10.15)
  Expected in: /usr/lib/libobjc.A.dylib

dyld: Symbol not found: _objc_alloc_init
  Referenced from: /Users/btfuser/./dummy_test (which was built for Mac OS X 10.15)
  Expected in: /usr/lib/libobjc.A.dylib

SIGABRT: abort
PC=0x846a1c2 m=0 sigcode=0

goroutine 0 [idle]:
runtime: unknown pc 0x846a1c2
stack: frame={sp:0x7ffeefbfe848, fp:0x0} stack=[0x7ffeefb80ad8,0x7ffeefbffb40)
00007ffeefbfe748:  000000005e6c0bf2  000000000591ccbe
00007ffeefbfe758:  000000005e6c0787  00000000142c6508
00007ffeefbfe768:  00000000000000c2  0000000000000008
00007ffeefbfe778:  0000000000001000  0000000000000000
00007ffeefbfe788:  0000000000000000  0000000000000000
00007ffeefbfe798:  0b643f06ddf700cf  000000000440bfd0
00007ffeefbfe7a8:  ffffffffffffffff  000000000440bfd0
00007ffeefbfe7b8:  000000c00003b000  00007ffeefbfe8a0
00007ffeefbfe7c8:  0000000008424c33  0000000008427c2b
00007ffeefbfe7d8:  000000000440bfd0  0000000000000000
00007ffeefbfe7e8:  000000000846a90e  0000000000000000
00007ffeefbfe7f8:  00007ffeefbff4b0  0000000000000000
00007ffeefbfe808:  0000000008423000  00007ffeefbff4e0
00007ffeefbfe818:  0000000000000000  00007ffeefbfec58
00007ffeefbfe828:  0000000000000005  000000000440c0d0
00007ffeefbfe838:  00007ffeefbff0b8  00007ffeefbff130
00007ffeefbfe848: <00000000084699b9  000000005ba470d6
00007ffeefbfe858:  000000200845ed37  00007ffeefbfe8b0
00007ffeefbfe868:  000000000000005a  00000000084a5e28
00007ffeefbfe878:  000000000000001e  000000000440bfd0
00007ffeefbfe888:  00007ffeefbfe8b0  00007ffeefbfe8a0
00007ffeefbfe898:  00000000084699eb  00007ffeefbff4d0
00007ffeefbfe8a8:  0000000008427aea  6e206c6f626d7953
00007ffeefbfe8b8:  646e756f6620746f  5f636a626f5f203a
00007ffeefbfe8c8:  6e695f636f6c6c61  66655220200a7469
00007ffeefbfe8d8:  206465636e657265  552f203a6d6f7266
00007ffeefbfe8e8:  6674622f73726573  642f2e2f72657375
00007ffeefbfe8f8:  7365745f796d6d75  6863696877282074
00007ffeefbfe908:  6975622073617720  4d20726f6620746c
00007ffeefbfe918:  205820534f206361  200a2935312e3031
00007ffeefbfe928:  6574636570784520  752f203a6e692064
00007ffeefbfe938:  6c2f62696c2f7273  412e636a626f6269
runtime: unknown pc 0x846a1c2
stack: frame={sp:0x7ffeefbfe848, fp:0x0} stack=[0x7ffeefb80ad8,0x7ffeefbffb40)
00007ffeefbfe748:  000000005e6c0bf2  000000000591ccbe
00007ffeefbfe758:  000000005e6c0787  00000000142c6508
00007ffeefbfe768:  00000000000000c2  0000000000000008
00007ffeefbfe778:  0000000000001000  0000000000000000
00007ffeefbfe788:  0000000000000000  0000000000000000
00007ffeefbfe798:  0b643f06ddf700cf  000000000440bfd0
00007ffeefbfe7a8:  ffffffffffffffff  000000000440bfd0
00007ffeefbfe7b8:  000000c00003b000  00007ffeefbfe8a0
00007ffeefbfe7c8:  0000000008424c33  0000000008427c2b
00007ffeefbfe7d8:  000000000440bfd0  0000000000000000
00007ffeefbfe7e8:  000000000846a90e  0000000000000000
00007ffeefbfe7f8:  00007ffeefbff4b0  0000000000000000
00007ffeefbfe808:  0000000008423000  00007ffeefbff4e0
00007ffeefbfe818:  0000000000000000  00007ffeefbfec58
00007ffeefbfe828:  0000000000000005  000000000440c0d0
00007ffeefbfe838:  00007ffeefbff0b8  00007ffeefbff130
00007ffeefbfe848: <00000000084699b9  000000005ba470d6
00007ffeefbfe858:  000000200845ed37  00007ffeefbfe8b0
00007ffeefbfe868:  000000000000005a  00000000084a5e28
00007ffeefbfe878:  000000000000001e  000000000440bfd0
00007ffeefbfe888:  00007ffeefbfe8b0  00007ffeefbfe8a0
00007ffeefbfe898:  00000000084699eb  00007ffeefbff4d0
00007ffeefbfe8a8:  0000000008427aea  6e206c6f626d7953
00007ffeefbfe8b8:  646e756f6620746f  5f636a626f5f203a
00007ffeefbfe8c8:  6e695f636f6c6c61  66655220200a7469
00007ffeefbfe8d8:  206465636e657265  552f203a6d6f7266
00007ffeefbfe8e8:  6674622f73726573  642f2e2f72657375
00007ffeefbfe8f8:  7365745f796d6d75  6863696877282074
00007ffeefbfe908:  6975622073617720  4d20726f6620746c
00007ffeefbfe918:  205820534f206361  200a2935312e3031
00007ffeefbfe928:  6574636570784520  752f203a6e692064
00007ffeefbfe938:  6c2f62696c2f7273  412e636a626f6269

goroutine 1 [syscall]:
runtime.cgocall(0x40a0f00, 0xc00003af18, 0x40d5a60)
	/usr/local/Cellar/go/1.14/libexec/src/runtime/cgocall.go:133 +0x5b fp=0xc00003aee8 sp=0xc00003aeb0 pc=0x40053bb
main._Cfunc_getFruits(0x0)
	_cgo_gotypes.go:71 +0x4a fp=0xc00003af18 sp=0xc00003aee8 pc=0x40a0a6a
main.main()
	/Users/tsekar/sources/test/dummy_test/main.go:39 +0x26 fp=0xc00003af88 sp=0xc00003af18 pc=0x40a0e36
runtime.main()
	/usr/local/Cellar/go/1.14/libexec/src/runtime/proc.go:203 +0x212 fp=0xc00003afe0 sp=0xc00003af88 pc=0x4032dd2
runtime.goexit()
	/usr/local/Cellar/go/1.14/libexec/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc00003afe8 sp=0xc00003afe0 pc=0x405d561

rax    0x2000209
rbx    0x0
rcx    0x7ffeefbfe848
rdx    0x7ffeefbfecb0
rdi    0x6
rsi    0x4
rbp    0x7ffeefbfe890
rsp    0x7ffeefbfe848
r8     0x7ffeefbfe8b0
r9     0x0
r10    0x5a
r11    0x246
r12    0x5a
r13    0x7ffeefbfecb0
r14    0x4
r15    0x6
rip    0x846a1c2
rflags 0x246
cs     0x7
fs     0x0
gs     0x0

Building the app on macOS mojave and running it on macOS catalina poses no issues. Doing it the other way around is causing the crash.

@ghost
Copy link
Author

ghost commented Mar 16, 2020

Adding the -mmacosx-version-min flag to CFLAGS fixes this issue. This seems to be caused by a change in Catalina. Closing.

@ghost ghost closed this as completed Mar 16, 2020
@randall77
Copy link
Contributor

Do you know if this is due to a specific C API you were using, or is this a general problem?
If the latter, we might want to fix this in the release. We do support Mojave, including cross-compiling from Catalina to Mojave (although not sure what exactly we guarantee about the cgo part of that).

@randall77
Copy link
Contributor

I can reproduce on 10.12.6 (an old mac I have lying around).

On 10.15.3, _objc_alloc_init exists:

% nm /usr/lib/libobjc.A.dylib | grep objc_alloc
00000000000231ac T _objc_alloc
00000000000231d8 T _objc_allocWithZone
0000000000023206 T _objc_alloc_init
000000000000f233 T _objc_allocateClassPair
000000000001bcb7 T _objc_allocateProtocol
0000000000014800 T _objc_allocate_object

On 10.12.6, it doesn't:

$ nm /usr/lib/libobjc.A.dylib | grep objc_alloc
000000000001346d t __Z25_objc_allocateFutureClassPKc
00000000000217b2 T _objc_alloc
0000000000021816 T _objc_allocWithZone
000000000001041e T _objc_allocateClassPair
00000000000190b1 T _objc_allocateProtocol
0000000000015e3d T _objc_allocate_object

So it looks like objective C isn't backwards compatible without adding a -mmacosx-version-min flag to the build.
I don't think there's any way we can fix this, unfortunately. The same thing happens for vanilla objective-c programs.

#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
    [[NSMutableArray alloc] init];
    return 0;
}

When run on 10.15.2, it works fine. On 10.12.6, it prints:

% gcc -framework Foundation hello.m  (on 10.15.2)
% ./a.out    (on 10.12.6)
dyld: lazy symbol binding failed: Symbol not found: _objc_alloc_init
  Referenced from: /Users/khr/a.out
  Expected in: /usr/lib/libobjc.A.dylib

dyld: Symbol not found: _objc_alloc_init
  Referenced from: /Users/khr/a.out
  Expected in: /usr/lib/libobjc.A.dylib

Abort trap: 6

@ghost
Copy link
Author

ghost commented Mar 16, 2020

Yes. It does look like a general problem with the objective C complier, and adding - mmacosx-version-min flag fixes this.

This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants