Post

MacOS -- Getting started

I am using Macbook with M1 chip. The day-to-day develop experience is similar to working on Linux, but there are quite a few gotchas. For example, gdb is not available, so I can only use lldb.

The universal binary and the shim system.

Universal binaries are archives that embed one or more Mach-O objects. For example, file type of python3 is a Mach-O universal binary. You can read this great post to learn about the motivation and various tools to explore universal binaries.

1
2
3
4
$ file /usr/bin/python3
/usr/bin/python3: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e]
/usr/bin/python3 (for architecture x86_64):     Mach-O 64-bit executable x86_64
/usr/bin/python3 (for architecture arm64e):     Mach-O 64-bit executable arm64e

Also, this file does not contain the real python binary. It is just a shim that point to the binary. Usually shims are just symbolic links to the real binary. This is different in MacOS. These shims are generated by Xcode and are actually binaries. Let’s take a look at python3.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
$ nm /usr/bin/python3

/usr/bin/python3 (for architecture x86_64):
                 U __NSConcreteGlobalBlock
                 U __NSGetExecutablePath
                 U __NSGetProgname
0000000100004058 s ___block_descriptor_tmp
0000000100004078 s ___block_literal_global
                 U ___error
0000000100003983 t ___mainExecutableToolName_block_invoke
                 U ___stack_chk_fail
                 U ___stack_chk_guard
0000000100000000 T __mh_execute_header
                 U _dispatch_once
                 U _getattrlist
00000001000038d5 t _main
0000000100008008 b _mainExecutableToolName.once
0000000100008010 b _mainExecutableToolName.toolName
0000000100008000 s _shim_marker
                 U _strcmp
                 U _strdup
                 U _strrchr
                 U _xcselect_invoke_xcrun

/usr/bin/python3 (for architecture arm64e):
                 U __NSConcreteGlobalBlock
                 U __NSGetExecutablePath
                 U __NSGetProgname
0000000100004058 s ___block_descriptor_tmp
0000000100004078 s ___block_literal_global
                 U ___error
00000001000038b4 t ___mainExecutableToolName_block_invoke
                 U ___stack_chk_fail
                 U ___stack_chk_guard
0000000100000000 T __mh_execute_header
                 U _dispatch_once
                 U _getattrlist
00000001000037f0 t _main
0000000100008008 b _mainExecutableToolName.once
0000000100008010 b _mainExecutableToolName.toolName
0000000100008000 s _shim_marker
                 U _strcmp
                 U _strdup
                 U _strrchr
                 U _xcselect_invoke_xcrun

Just want to point out symbol _shim_maker and _xcselect_invoke_xcrun. I do not have access to the source code of these functions, but I can guess what they do.

xcrun is a command-line tool on macOS that provides a way to locate or run other tools and utilities that are stored within the Xcode toolchain.

The target object of this shim is below.

1
2
3
4
5
$ xcrun -f python3
/Library/Developer/CommandLineTools/usr/bin/python3

$ ll /Library/Developer/CommandLineTools/usr/bin/python3
lrwxr-xr-x  1 root  wheel    67B Jan  2 12:29 /Library/Developer/CommandLineTools/usr/bin/python3 -> ../../Library/Frameworks/Python3.framework/Versions/3.9/bin/python3

So basically, the real python installed in my laptop is at /Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9/bin/python3. You can check that this file is also a universal binary.

This post is licensed under CC BY 4.0 by the author.